package com.example.securitydemo.filter;

import com.example.securitydemo.util.JwtUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.SignatureException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * JWT请求过滤器，用于处理每个请求中的JWT令牌。
 * 该类继承自OncePerRequestFilter，确保每个请求只被过滤一次。
 */
public class JwtRequestFilter extends OncePerRequestFilter {

    private final JwtUtil jwtUtil;
    private final UserDetailsService userDetailsService;

    /**
     * 构造函数。
     *
     * @param jwtUtil             JWT工具类，用于解析和验证令牌
     * @param userDetailsService 用户详情服务，用于加载用户信息
     */
    public JwtRequestFilter(JwtUtil jwtUtil, UserDetailsService userDetailsService) {
        this.jwtUtil = jwtUtil;
        this.userDetailsService = userDetailsService;
    }

    /**
     * 内部过滤方法，处理每个请求。
     * 该方法会检查请求头中的Authorization字段，解析JWT令牌，并设置Spring Security上下文。
     *
     * @param request  HTTP请求
     * @param response HTTP响应
     * @param chain    过滤器链，用于继续执行后续过滤器
     * @throws ServletException 如果发生Servlet异常
     * @throws IOException      如果发生I/O异常
     */
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        String authorizationHeader = request.getHeader("Authorization");

        if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
            String token = authorizationHeader.substring(7);
            try {
                Claims claims = jwtUtil.parseToken(token);
                String username = claims.getSubject();
                @SuppressWarnings("unchecked")
                List<String> authorities = (List<String>) claims.get("authorities");
                if (authorities == null) {
                    authorities = new ArrayList<>();
                }

                UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
                        username, null, authorities.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList()));

                SecurityContextHolder.getContext().setAuthentication(auth);
            } catch (SignatureException e) {
                // 当签名不匹配时，返回 403 Forbidden 状态码
                response.setStatus(HttpServletResponse.SC_FORBIDDEN);
                return;
            } catch (Exception e) {
                // 处理其他可能的异常，返回 500 Internal Server Error 状态码
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                return;
            }
        }

        chain.doFilter(request, response);
    }
}